package com.lyf.boot.utils;

import cn.hutool.core.io.IoUtil;
import cn.hutool.extra.servlet.JakartaServletUtil;
import cn.hutool.json.JSONUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.MediaType;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

/**
 * @author Luyufan
 * @date 2023/7/4 13:45
 */
@Slf4j
public class ServerUtil {

    public static ServletRequestAttributes requestAttributes(){
        // 从请求上下文里获取Request对象
        return (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    }

    public static HttpServletRequest request(){
        return requestAttributes().getRequest();
    }

    public static HttpServletResponse response(){
        return requestAttributes().getResponse();
    }

    public static String clientIp(){
        return JakartaServletUtil.getClientIP(request());
    }

    /**
     * 获取IP地址
     *
     * @return 本地IP地址
     */
    public static String getHostIp(){
        try{
            return InetAddress.getLocalHost().getHostAddress();
        }catch (UnknownHostException e){
            log.error("ip获取失败");
        }
        return "127.0.0.1";
    }

    /**
     * 获取主机名
     *
     * @return 本地主机名
     */
    public static String getHostName(){
        try{
            return InetAddress.getLocalHost().getHostName();
        }catch (UnknownHostException e){
            log.error("主机名获取失败");
        }
        return "未知";
    }

    public static String getIpRegion(String ip) {
        //String dbPath = ServerUtil.class.getClassLoader().getResource("ip2region.xdb").getPath();
        byte[] cBuff;
        try {
            ClassPathResource resource = new ClassPathResource("/ip2region.xdb");
            InputStream inputStream = resource.getInputStream();
            cBuff = IoUtil.readBytes(inputStream);
        } catch (Exception e) {
            //log.error("failed to load content from `{}`: {}\n", dbPath, e);
            return null;
        }
        Searcher searcher;
        try {
            searcher = Searcher.newWithBuffer(cBuff);
        } catch (IOException e) {
            //log.error("failed to create searcher with `{}`: {}\n", dbPath, e);
            return null;
        }
        // 2、查询
        try {
            long sTime = System.nanoTime();
            String region = searcher.search(ip);
            long cost = TimeUnit.NANOSECONDS.toMicros(System.nanoTime() - sTime);
            log.debug("{region: {}, ioCount: {}, took: {} μs}\n", region, searcher.getIOCount(), cost);
            return region;
        } catch (Exception e) {
            log.error("failed to search({}): {}\n", ip, e.getMessage(), e);
        } finally {
            // 3、关闭资源
            try {
                searcher.close();
            } catch (IOException e) {
                log.error("failed to close searcher: {}\n", e.getMessage(), e);
            }
        }
        return null;
    }

    public static void setApplicationJson(HttpServletResponse response){
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        response.setHeader("content-type", MediaType.APPLICATION_JSON_VALUE);
    }

    public static void write(HttpServletResponse response, Object obj){
        setApplicationJson(response);
        try {
            response.getWriter().write(JSONUtil.toJsonStr(obj));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
